package com.mezz.bones.im.gateway.handler;

import com.mezz.bones.framework.core.strategy.StrategyContext;
import com.mezz.bones.im.common.enums.ActionCodeEnum;
import com.mezz.bones.im.common.event.MessageReceivedEvent;
import com.mezz.bones.im.common.exception.ImBaseException;
import com.mezz.bones.im.common.message.base.Message;
import com.mezz.bones.im.common.message.base.MessageHeader;
import com.mezz.bones.im.common.domain.user.ImUserConnectInfo;
import com.mezz.bones.im.common.process.IMessageProcessor;
import com.mezz.bones.im.common.result.ImResult;
import com.mezz.bones.im.common.result.ImResultCode;
import com.mezz.bones.im.gateway.action.interfaces.SysMessageAction;
import com.mezz.bones.im.gateway.manager.UserConnectInfoManager;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;

/**
 * @author mezz
 * @date 2022-09-23 14:08
 * @description:
 * 检测channel心跳
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class ImServerHandler extends SimpleChannelInboundHandler<Message> {

  @Resource
  private IMessageProcessor messagePublisher;

  @Resource
  private StrategyContext strategyContext;

  @Resource(name = "imSysMessageActionExecutor")
  private ThreadPoolTaskExecutor imSysMessageActionExecutor;

  @Resource(name = "imBizMessageActionExecutor")
  private ThreadPoolTaskExecutor imBizMessageActionExecutor;

  @Resource
  private UserConnectInfoManager userConnectInfoManager;


  /**
   * websocket 处理具体业务
   * @param ctx
   * @param msg
   * @throws Exception
   */
  @Override
  protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {

    log.debug("-----------ImServerHandler begin-----------");

    //消息发送端
    ImUserConnectInfo senderUserConnectInfo = userConnectInfoManager.getUserConnectInfo(ctx);
    MessageHeader header = msg.getHeader();
    String traceId = header.getTraceId();
    String actionCode = header.getActionCode();
    ActionCodeEnum actionCodeEnum = ActionCodeEnum.findEnum(actionCode);

    if(actionCodeEnum.getAuthIgnore() == 0) {
      //业务消息必须是登录态
      if(senderUserConnectInfo == null){
        ctx.channel().writeAndFlush(ImResult.data(ImResultCode.USER_NOT_LOGIN,traceId,ActionCodeEnum.SERVER_ERROR.getCode(), null));
        return;
      }
    }

    //异步处理消息
    if (msg.codeType() == 0) {
      //系统消息 直接在网关层面解决
      //ping
      imSysMessageActionExecutor.execute(()->{
        SysMessageAction<?> sysMessageAction = strategyContext.getStrategy(SysMessageAction.class, msg.getHeader().getActionCode());
        try {

          sysMessageAction.handler(msg,ctx);
        } catch (ImBaseException e) {

          log.error("handlerSysMessageAction ImBaseException ",e);
          ImResultCode resultCode = e.getResultCode();
          ctx.channel().writeAndFlush(ImResult.data(resultCode,traceId,ActionCodeEnum.SERVER_ERROR.getCode(),null));

        } catch (Exception e) {
          log.error("handlerSysMessageAction Exception ",e);
          ctx.channel().writeAndFlush(ImResult.data(ImResultCode.SYS_ERROR,traceId,ActionCodeEnum.SERVER_ERROR.getCode(), null));
        }

      });

    }else {

      //业务消息 通过事件进行解耦
      imBizMessageActionExecutor.execute(()->{
        System.out.println(Thread.currentThread().getName());
        MessageReceivedEvent messageReceivedEvent = new MessageReceivedEvent(senderUserConnectInfo,msg);
        // 业务层的MessageReceiveListener监听器 处理具体业务
        messagePublisher.dispatchMessage2Logic(messageReceivedEvent);
      });
    }

  }

}
